package ferp.core.mode;

import ferp.core.ai.tree2.Evaluator;
import ferp.core.ai.tree2.Score;
import ferp.core.calc.Calculator;
import ferp.core.game.Game;
import ferp.core.game.Input;
import ferp.core.game.Settings;
import ferp.core.player.Player;
import ferp.core.player.Profile;
import ferp.core.state.State;

/**
 * User: olegs
 * Date: 19/05/11 15:12
 */
public class Misere extends Moving
{
  @Override
  public int initialize(Game.Listener listener, Profile profile, Game g, Settings settings) throws Game.Error
  {
    if (g.declarer() != g.human() && settings.misereMode == Settings.MisereMode.ANDROID && settings.skipGameOnPass)
    {
      // make the opponent to be an AI that plays against the declarer
      g.player.opponent = Game.PLAYERS - g.player.declarer;
      // switch to fast moving state
      g.set(State.fastMoving);

      return State.Result.SCHEDULE;
    }

    return super.initialize(listener, profile, g, settings);
  }

  @Override
  public Player mover(Game g, Settings settings, int current)
  {
    // declarer always plays for himself as well as human if he's a declarer
    if (current != g.player.declarer && g.declarer() != g.human())
    {
      switch (settings.misereMode)
      {
        case HUMAN:
          return g.human();

        case ANDROID:
          return g.player(Game.PLAYERS - g.player.declarer);
      }
    }

    return super.mover(g, settings, current);
  }

  @Override
  public int evaluator()
  {
    return Evaluator.MISERE;
  }

  @Override
  public void score(Game g, Settings settings)
  {
    Calculator.get(settings.gameFlavor).misere(g, settings);

    // depends on settings, reset consequent passing sets counter if the declarer took no tricks
    if (settings.isPassingInterruptedByMisere(g.getDeclarerTricks()))
      g.consequentPassingSets = 0;
  }

  @Override
  protected int options(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    // open non-declarer's cards on first round
    if (g.rounds == 0 && g.player.current != g.player.declarer && g.type == Game.Type.UNKNOWN)
    {
      Player opponent1 = g.next(g.declarer());
      Player opponent2 = g.next(opponent1);

      g.getHand(opponent1.id()).open = true;
      g.getHand(opponent2.id()).open = true;

      // force game type to open
      g.type = Game.Type.OPEN;

      listener.onOpenGameType(g, settings, opponent1, opponent2);
    }

    return super.options(listener, g, settings, input);
  }

  @Override
  protected Act act(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    switch (input.offer)
    {
      case REST_TRICKS_ARE_MINE:
        // score is relative => number of rounds to play has to be equal or greater than score
        int rest = Game.MAXIMUM_ROUNDS - g.rounds;

        if (rest >= Score.get((short)input.score, g.player.current))
        {
          g.addTricks(g.player.current, rest);

          return Act.DONE;
        }

        listener.onOfferDeclined();

        return Act.STAY;

      case NO_MORE_TRICKS:
        // score is relative => it must be equal to 0
        if (Score.get((short)input.score, g.player.current) == 0)
        {
          // find a victim to put remaining tricks on - it must be the player other than the current player and the declarer
          Player victim = g.next(g.current());

          if (victim == g.declarer())
            victim = g.next(victim);

          g.addTricks(victim.id(), Game.MAXIMUM_ROUNDS - g.rounds);

          return Act.DONE;
        }

        listener.onOfferDeclined();

        return Act.STAY;
    }

    if (g.declarer() != g.human() && g.declarer() == g.current())
      listener.markMisereMove(input.card);

    return super.act(listener, g, settings, input);
  }

  @Override
  protected void setMoverInputOptions(Game.Listener listener, Game g, Player mover) throws Game.Error
  {
    mover.setMisereInputOptions(listener, g);
  }

}
